package com.sugar.uitls;

/**
 * @author felix
 * @date 2025/5/12 15:15
 */
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RSAUtil {
    private static final String ALGORITHM_NAME = "RSA";

    /**
     * 生成秘钥对
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, String> generateKeyPair() {
        Security.addProvider(new BouncyCastleProvider());
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            /*        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();*/
            String publicKey = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
            String privateKey = Base64.encodeBase64String((keyPair.getPrivate().getEncoded()));
            Map<String, String> keyMap = new HashMap<>();
            keyMap.put("publicKey", publicKey);
            keyMap.put("privateKey", privateKey);
            return keyMap;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密
     * @param string
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String encrypt(String string, String publicKey) {
        try {
            byte[] decoded = Base64.decodeBase64(publicKey);
            PublicKey pubKey = KeyFactory.getInstance(ALGORITHM_NAME).generatePublic(new X509EncodedKeySpec(decoded));

            Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
            //Cipher encryptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "BC");
            //OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
            //encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey, oaepParams);
            encryptCipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] encryptedData = encryptCipher.doFinal(string.getBytes());
            return Base64.encodeBase64String(encryptedData);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
                 BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
        return "";
    }

    /**
     *解密
     * @param string
     * @param privateKeyStr
     * @return
     * @throws Exception
     */
    public static String decrypt(String string, String privateKeyStr){
        try {
            PrivateKey privateKey = KeyFactory.getInstance(ALGORITHM_NAME).generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)));

            Cipher decryptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
            //Cipher decryptCipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING", "BC");
            //OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);
            //decryptCipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParams);
            decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decryptedData = decryptCipher.doFinal(Base64.decodeBase64(string));
            return new String(decryptedData);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
        return "";
    }
}

